package flib;

import java.awt.Container;
import java.awt.Frame;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.util.Vector;

import processing.core.PApplet;
import processing.event.KeyEvent;
import simpleGui.PCam2DGraphics;

public class FlibEditor extends PApplet implements ActionListener, ItemListener{

MenuBar myMenu;	
	
String pathImageFolder;
String pathOBJFolder;
static final int LINE=0,POLYLINE=1,SELECT=2;
int editMode=0;
FlibHENode selectedNode;
FlibHENode closestNode;
FlibWall closestWall;
FlibFace closestRoom;
FlibHENode firstNode;
FlibHENode secondNode;

Vector<FlibWall>sel_Walls=new Vector<FlibWall>();
//Vector<FlibHENode>sel_Nodes;
Vector<FlibFace>sel_Rooms=new Vector<FlibFace>();

PCam2DGraphics cam;
FlibLevel selectedLevel;

boolean flagSave;
boolean flagLoad;
boolean flagAddNode;
boolean flagAddLine;
boolean flagSelect;
boolean flagMultiSelect;
boolean flagDelete;

float minNodeDist=0.2f;// 1cm away from node or wall

// addNode
// action drawline
// move node

int pickingDist=20;
float xModel;

float yModel;
public void setup(){
	myMenu = new MenuBar();
	Menu menuFile = new Menu("File");
	myMenu.add(menuFile);
	
	
	size(1600,900);
	smooth();
	cam=new PCam2DGraphics(this);
	findFrame().setMenuBar(myMenu);
	selectedLevel=new FlibLevel();
}
	public Frame findFrame() {		
    Container f = this.getParent();
    while (!(f instanceof Frame) && f!=null)
          f = f.getParent();
    return (Frame) f;
}
	public void draw() {
		xModel=cam.getModelX(mouseX);
		yModel=cam.getModelY(mouseY);
		findClosest();
		if (flagAddNode) {
			if (firstNode==null){
				firstNode = addNode(xModel,yModel);
			}
			else{
				FlibHENode secondNode=addNode(xModel,yModel);
				if (secondNode!=firstNode){
					addWall(firstNode,secondNode);
					firstNode=secondNode;
				}
			}
			flagAddNode = false;
		}
		if (flagSelect){
			select();
			flagMultiSelect=false;
			flagSelect=false;
		}
		if (flagDelete){
			delete();
			flagDelete=false;
		}
		if (flagSave) {
			flagSave = false;
		}
		if (flagLoad) {
			flagLoad = false;
		}
		display();
	}
	
	
	public void display(){
		cam.useCam(g);
		background(20);
		stroke(255);
		
		if (selectedLevel != null) {
			fill(100);
			for (int i = 0; i < selectedLevel.rooms.size(); i++) {
				FlibFace room = selectedLevel.rooms.get(i);
				room.display(g);
			}
			fill(255,200,200);
			for (int i = 0; i < sel_Rooms.size(); i++) {
				FlibFace room = sel_Rooms.get(i);
				room.display(g);
			}
			strokeWeight(4f);
			if (closestWall!=null){
				closestWall.display2D(g);
				float[] result=new float[2];
				closestWall.getClosestPointToSeg(xModel, yModel, result);
				ellipse(result[0],result[1],20,20);
			}
			strokeWeight(2f);
			stroke(255,0,0);
			for (int i = 0; i < sel_Walls.size(); i++) {
				FlibWall wall = sel_Walls.get(i);
				wall.display2D(g);
			}
			stroke(255);
			strokeWeight(1f);
			for (int i = 0; i < selectedLevel.walls.size(); i++) {
				FlibWall wall = selectedLevel.walls.get(i);
				wall.display2D(g);
			}
			if (firstNode!=null){
				line(firstNode.x,firstNode.y,xModel,yModel);
			}
			if (closestNode!=null){
				ellipse(closestNode.x,closestNode.y,20,20);
			}
			for (int i = 0; i < selectedLevel.nodes.size(); i++) {
				FlibHENode node = selectedLevel.nodes.get(i);
				ellipse(node.x, node.y, 10, 10);
			}
		}
		
	}

public void findClosest(){
	if (selectedLevel!=null){
		closestNode=selectedLevel.getClosestNode2D(xModel,yModel);
		if (closestNode!=null){
			float dist=closestNode.dist(xModel,yModel);
			if (dist*cam.scale>pickingDist){
				closestNode=null;
			}
		}
		
		closestWall=selectedLevel.getClosestWall2D(xModel,yModel);
		if (closestWall!=null){
		float dist=closestWall.distToSeg(xModel,yModel);
		if (dist*cam.scale>pickingDist){
			closestWall=null;
		}
		}
		
		closestRoom=selectedLevel.getContainingRoom2D(xModel,yModel);
	}
}


public void load(String file){
	
}
public void save(String file){
	
}

public void pullHistory(){
	
}
public void pushHistory(){
	
}

public FlibHENode addNode(float x,float y){
	// if its a Node return it
	//FlibHENode closestNode=selectedLevel.getClosestNode2D(x,y);
	if (closestNode!=null){
		return closestNode;
	}
	// if its onLine: split HEdge
	
	if (closestWall!=null){
		float wallD=closestWall.distToSeg(x, y);
	
		float[] result=new float[2];
		closestWall.getClosestPointToSeg(x, y, result);
		FlibHENode node=selectedLevel.addNode(result[0],result[1]);
		selectedLevel.splitWall(closestWall, node);
		return node;
		
	}
	return selectedLevel.addNode(x, y);
}
public void addWall(FlibHENode n1, FlibHENode n2){
	selectedLevel.addWallIntersect(n1,n2); 
}
public void delete(){
	if (selectedLevel!=null){
	for (int i=0;i<sel_Walls.size();i++){
		FlibWall wall=sel_Walls.get(i);
		selectedLevel.removeWall(wall);
	}
	sel_Walls.clear();
	sel_Rooms.clear();
	}
}
public void select(){
	boolean wallIsSelected=sel_Walls.contains(closestWall);
	boolean roomIsSelected=sel_Rooms.contains(closestRoom);
	if (!flagMultiSelect){
		sel_Walls.clear();
		sel_Rooms.clear();
	}
	if (closestWall!=null){
		if (!wallIsSelected)
			sel_Walls.add(closestWall);
		else sel_Walls.remove(closestWall);
	}
	else if (closestRoom!=null){
		if (!roomIsSelected)
			sel_Rooms.add(closestRoom);
		else sel_Rooms.remove(closestRoom);
	}
}



@Override
public void mouseDragged(MouseEvent e) {
	// TODO Auto-generated method stub
	super.mouseDragged(e);
}

@Override
public void mouseMoved(MouseEvent e) {
	// TODO Auto-generated method stub
	super.mouseMoved(e);
}

@Override
public void mousePressed(MouseEvent e) {
	// TODO Auto-generated method stub
	if (editMode == SELECT) {
		flagSelect=true;
		if (e.isShiftDown()){
			flagMultiSelect=true;
		}
	}
	if (!e.isShiftDown()){
	super.mousePressed(e);
	}
	
}

@Override
public void mouseReleased(MouseEvent e) {
	// TODO Auto-generated method stub
		if (!cam.isDragMode() && !e.isAltDown() && !e.isControlDown()
				&& !e.isShiftDown()) {
			if (editMode == LINE) {
				flagAddNode = true;
			}
		}
		super.mouseReleased(e);
}
@Override
public void itemStateChanged(ItemEvent arg0) {
	// TODO Auto-generated method stub
	
}

@Override
public void actionPerformed(ActionEvent arg0) {
	// TODO Auto-generated method stub
	
}


@Override
public void keyPressed() {
	// TODO Auto-generated method stub
	if (key==this.ESC){
		firstNode=null;
	}
	if (key=='1'){
		editMode=SELECT;
	}
	if (key==DELETE||key==BACKSPACE){
		flagDelete=true;
	}
	key=0;
	
}


}
